#include "levelstate.h"

void LevelState::ServerInit()
{
	m_work_manager = m_server->work_manager();
	m_guid = m_server->GetGUID();
}

void LevelState::ServerCleanup()
{
	if (m_shutdown_network_on_state_end)
	{
		m_server->Shutdown();
		delete m_server;
	}
}

void LevelState::DoServerWork()
{
	Job next_job;
	while (m_work_manager->GetJobToLocal(next_job))
	{
		unsigned char type_id;
		next_job.data->Read(type_id);
		switch (type_id)
		{
			// TODO: Handle new connection. We can just kick them or send a special message that the game has already
			// started or we can even tell the server to not allow any more connections.
		case ID_DISCONNECTION_NOTIFICATION:
		case ID_CONNECTION_LOST:
			ServerRemovePlayer(next_job.sender_guid);
			break;
		};

		next_job.JobDone();
	}
}

void LevelState::ServerRemovePlayer(std::string guid)
{
	// Remove the client.
	m_client_list.RemoveClient(guid);

	// Tell everyone that the client removed is not there anymore.				
	Job job(ID_REMOVE_CLIENT);
	RakNet::StringCompressor::Instance()->EncodeString(RakNet::RakString(guid.c_str()), 64, job.data);

	job.broadcast = true;
	m_work_manager->JobToRemote(job);
}

void LevelState::ServerKickPlayer(std::string guid)
{
	// Close the connection. This will automatically trigger an ID_DISCONNECTION_NOTIFICATION which will then
	// trigger the ServerRemovePlayer command below.
	m_server->CloseConnection(guid);
}

void LevelState::ServerUpdate(float timing_factor)
{
	DoServerWork();

	// Open the entries if it is time.
	if (!m_opened && m_time_running > STANDARD_TIME_TO_OPEN)
	{
		m_opened = true;
		m_level->OpenEntries();

		// Tell all clients to open the entries.
		Job job(ID_OPEN_ENTRIES);
		job.broadcast = true;
		m_work_manager->JobToRemote(job);
	}

	// Tell the entries to start release Lems if it is time.
	if (!m_release_started && m_time_running > STANDARD_TIME_TO_RELEASE)
	{
		m_release_started = true;
		m_level->StartToRelease();

		// Tell all clients that we start spawning.
		Job job(ID_START_SPAWN);
		job.broadcast = true;
		m_work_manager->JobToRemote(job);
	}
}